package com.credithc.signature.common.utils;

import lombok.extern.slf4j.Slf4j;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

@Slf4j
public class TimeUtil {

    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");


    public static Date yesterday(Date today) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(today);
        calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - 1);
        return calendar.getTime();
    }

    /**
     * 获取过期时间
     *
     * @param seconds
     * @return
     */
    private static String timeAdd(long seconds) {
        Calendar nowTime = Calendar.getInstance();
        nowTime.add(Calendar.SECOND, (int) seconds / 1000);
        return sdf.format(nowTime.getTime());
    }

    /**
     * 获取过期时间
     *
     * @param milliseconds
     * @return
     */
    public static Date getExpireTime2(int milliseconds) {
        try {
            String timeAdd = timeAdd(milliseconds);
            return sdf.parse(timeAdd);
        } catch (ParseException e) {
            log.error("获取过期时间发生异常", e);
        }
        return null;
    }

    /**
     * 获取过期时间
     *
     * @param seconds
     * @return
     */
    public static Date getExpireTime(long seconds) {
        try {
            String timeAdd = timeAdd(seconds);
            return sdf.parse(timeAdd);
        } catch (ParseException e) {
            log.error("获取过期时间发生异常", e);
        }
        return null;
    }

    /**
     * 获取过期时间
     *
     * @param year
     * @return
     */
    public static Date getExpireTime(int year) {
        Calendar nowTime = Calendar.getInstance();
        nowTime.add(Calendar.YEAR, year);//增加一年
        return nowTime.getTime();
    }

    /**
     * 获取当前时间
     */
    public static String getTime(Date date) {
        return sdf.format(date);
    }

    // 获取当天的开始时间
    public static Date getDayBegin() {
        Calendar cal = new GregorianCalendar();
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    // 获取当天的结束时间
    public static Date getDayEnd() {
        Calendar cal = new GregorianCalendar();
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        return cal.getTime();
    }

    // 获取本周的开始时间
    @SuppressWarnings("unused")
    public static Date getBeginDayOfWeek() {
        Date date = new Date();
        if (date == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int dayofweek = cal.get(Calendar.DAY_OF_WEEK);
        if (dayofweek == 1) {
            dayofweek += 7;
        }
        cal.add(Calendar.DATE, 2 - dayofweek);
        return getDayStartTime(cal.getTime());
    }

    // 获取本周的结束时间
    public static Date getEndDayOfWeek() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(getBeginDayOfWeek());
        cal.add(Calendar.DAY_OF_WEEK, 6);
        Date weekEndSta = cal.getTime();
        return getDayEndTime(weekEndSta);
    }

    // 获取上周的开始时间
    @SuppressWarnings("unused")
    public static Date getBeginDayOfLastWeek() {
        Date date = new Date();
        if (date == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int dayofweek = cal.get(Calendar.DAY_OF_WEEK);
        if (dayofweek == 1) {
            dayofweek += 7;
        }
        cal.add(Calendar.DATE, 2 - dayofweek - 7);
        return getDayStartTime(cal.getTime());
    }

    // 获取上周的结束时间
    public static Date getEndDayOfLastWeek() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(getBeginDayOfLastWeek());
        cal.add(Calendar.DAY_OF_WEEK, 6);
        Date weekEndSta = cal.getTime();
        return getDayEndTime(weekEndSta);
    }

    // 获取本月的开始时间
    public static Date getBeginDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(getNowYear(), getNowMonth() - 1, 1);
        return getDayStartTime(calendar.getTime());
    }

    // 获取本月的结束时间
    public static Date getEndDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(getNowYear(), getNowMonth() - 1, 1);
        int day = calendar.getActualMaximum(5);
        calendar.set(getNowYear(), getNowMonth() - 1, day);
        return getDayEndTime(calendar.getTime());
    }

    // 获取上月的开始时间
    public static Date getBeginDayOfLastMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(getNowYear(), getNowMonth() - 2, 1);
        return getDayStartTime(calendar.getTime());
    }

    // 获取上月的结束时间
    public static Date getEndDayOfLastMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(getNowYear(), getNowMonth() - 2, 1);
        int day = calendar.getActualMaximum(5);
        calendar.set(getNowYear(), getNowMonth() - 2, day);
        return getDayEndTime(calendar.getTime());
    }

    // 获取今年是哪一年
    public static Integer getNowYear() {
        Date date = new Date();
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        return Integer.valueOf(gc.get(1));
    }

    // 获取本月是哪一月
    public static int getNowMonth() {
        Date date = new Date();
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        return gc.get(2) + 1;
    }

    // 获取某个日期的开始时间
    public static Timestamp getDayStartTime(Date d) {
        Calendar calendar = Calendar.getInstance();
        if (null != d) {
            calendar.setTime(d);
            calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
            calendar.set(Calendar.MILLISECOND, 0);
        }
        return new Timestamp(calendar.getTimeInMillis());
    }

    // 获取某个日期的结束时间
    public static Timestamp getDayEndTime(Date d) {
        Calendar calendar = Calendar.getInstance();
        if (null != d) {
            calendar.setTime(d);
            calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
            calendar.set(Calendar.MILLISECOND, 999);
        }
        return new Timestamp(calendar.getTimeInMillis());
    }

    /**
     * 获取时间差--格式yyyyMMdd字符串
     *
     * @param start
     * @param end
     * @return
     */
    public static Long betWeenDays(Date start, Date end) {
        Instant startInstant = start.toInstant();
        Instant endInstant = end.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDate startLocalDate = startInstant.atZone(zoneId).toLocalDate();
        LocalDate endLocalDate = endInstant.atZone(zoneId).toLocalDate();
        long days = ChronoUnit.DAYS.between(startLocalDate, endLocalDate);
        return days;
    }

    /**
     * 获取前一天
     *
     * @param start
     * @param days
     * @return
     */
    public static Date prevDay(Date start, Integer days) {
        Instant startInstant = start.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDate startLocalDate = startInstant.atZone(zoneId).toLocalDate();
        LocalDate minusDate = startLocalDate.minus(days, ChronoUnit.DAYS);
        Instant instant = minusDate.atStartOfDay().atZone(zoneId).toInstant();
        Date nextDate = Date.from(instant);
        return nextDate;
    }

    /**
     * 获取下一天
     *
     * @param start
     * @param days
     * @return
     */
    public static Date nextDay(Date start, Integer days) {
        Instant startInstant = start.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDate startLocalDate = startInstant.atZone(zoneId).toLocalDate();
        LocalDate plusDate = startLocalDate.plus(days, ChronoUnit.DAYS);
        Instant instant = plusDate.atStartOfDay().atZone(zoneId).toInstant();
        Date nextDate = Date.from(instant);
        return nextDate;
    }

    /**
     * 获取前几个小时
     *
     * @param times
     * @param pattern
     * @return
     */
    public static String prevTime(Integer times, String pattern) {
        LocalDateTime dateTime = LocalDateTime.now().minusHours(times);
        String formatTime = dateTime.format(DateTimeFormatter.ofPattern(pattern));
        return formatTime;
    }

    /**
     * 获取当前时间
     *
     * @param pattern
     * @return
     */
    public static String nowTime(String pattern) {
        LocalDateTime dateTime = LocalDateTime.now();
        String formatTime = dateTime.format(DateTimeFormatter.ofPattern(pattern));
        return formatTime;
    }

    /**
     * 解析字符串时间
     *
     * @param time
     * @return
     */
    public static Date parseTime(String time) {
        try {
            return sdf.parse(time);
        } catch (ParseException e) {
            log.error("字符串时间转换异常......", e);
        }
        return null;
    }
}
